package com.cxw.healthserver.type_handler

import com.cxw.healthserver.utils.gson.JsonUtils
import org.apache.ibatis.type.BaseTypeHandler
import org.apache.ibatis.type.JdbcType
import org.apache.ibatis.type.MappedJdbcTypes
import org.apache.ibatis.type.MappedTypes
import java.lang.reflect.Type
import java.sql.CallableStatement
import java.sql.PreparedStatement
import java.sql.ResultSet
import java.sql.SQLException

@MappedJdbcTypes(JdbcType.VARBINARY)
@MappedTypes(MutableList::class) //继承BaseTypeHandler类，这个类是mybatis plus提供的基础类型处理类

abstract class ListTypeHandler<T> : BaseTypeHandler<List<T>?>() {

    /**
     * 保存数据前，会调用这个方法
     *
     *
     * ps 就是我们jdbc的 ps
     * i 对应参数保存sql中的位置，比如说我们以前用jdbc的时候，会写setString(i,value) ? -> value
     * List<T> 对应 BaseTypeHandler 上的泛型，parameter 对应实体类属性名
     * 其实这个参数就是获取到我们的实体类配了该处理器的属性的值，这里 parameter 为 department
     * jdbcType 如其名
    </T> */
    override fun setNonNullParameter(ps: PreparedStatement, i: Int, parameter: List<T>?, jdbcType: JdbcType?) {
        //如果参数有值，则用json转换器转换成json字符串，再把值set给ps
        //相当于在ps执行sql前，将值进行转换处理再放回sql里面去
        val content = if (parameter == null) null else JsonUtils.parseBean2json(parameter)
        ps.setString(i, content)
    }

    /**
     * 查询数据后， 会调用这个方法
     *
     *
     * rs 返回结果集，你懂jdbc的话应该不会陌生
     * columnName 加了转换器的属性对应的列名
     * rs.getString(columnName) 获取结果集中该列的值
     */
    @Throws(SQLException::class)
    override fun getNullableResult(rs: ResultSet, columnName: String): List<T>? {
        //用JSON类的方法把json字符串转换成集合对象
        return getListByJsonArrayString(rs.getString(columnName))
    }

    @Throws(SQLException::class)
    override fun getNullableResult(rs: ResultSet, columnIndex: Int): List<T>? {
        return getListByJsonArrayString(rs.getString(columnIndex))
    }

    @Throws(SQLException::class)
    override fun getNullableResult(cs: CallableStatement, columnIndex: Int): List<T>? {
        return getListByJsonArrayString(cs.getString(columnIndex))
    }

    //自定义的一个方法，用于处理查询结果中加了转换器的值
    private fun  getListByJsonArrayString(content: String?): List<T>? {
        return if (content == null) null else JsonUtils.parseJson2List(content, getBeanClass())
    }

    abstract fun getBeanClass():Class<T>
}